package pl.edu.pb.wi.cookbook.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import pl.edu.pb.wi.cookbook.entity.User;
import pl.edu.pb.wi.cookbook.util.FullTextSearchUtil;
import pl.edu.pb.wi.cookbook.util.HashUtil;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.Query;

@Service
public class UserService implements IFullTextSearch<User> {
    private Objectify oby;

    @Autowired
    public UserService(ObjectifyFactory objectifyFactory) {
        this.oby = objectifyFactory.begin();
    }

    public User getUserByLogin(String login) {
        return oby.query(User.class).filter("login", login).get();
    }

    public User getUserByKey(Key<User> userKey) {
        return oby.get(userKey);
    }

    public User getUserById(Long id) {
        return oby.get(new Key<User>(User.class, id));
    }

    public User getUserByValidationHash(String hash) {
        return oby.query(User.class).filter("validationHash", hash).get();
    }

    public User getUserByEmail(String email) {
        return oby.query(User.class).filter("email", email).get();
    }

    public boolean isUserIsValidated(User user) {
        User tmp = oby.get(new Key<User>(User.class, user.getId()));
        return tmp == null ? false : tmp.isValidated();
    }

    public Key<User> addUser(User user) {
        user.updateFts();

        return oby.put(user);
    }

    public User createUser(String login, String password, String email) {
        User newUser = new User();
        newUser.setLogin(login);
        newUser.setPassword(HashUtil.hashInput(password));
        newUser.setEmail(email);
        newUser.setCreatedAt(new Date());
        // Powinno być null, ale żeby było łatwiej przymkniemy oko.
        newUser.setLastLoginAt(new Date());
        newUser.setAdmin(false);
        // Na razie validation hash to po prostu MD5 wyciągnięte
        // z hasła.
        newUser.setValidationHash(String.format("%s%s",
                HashUtil.hashInput(login), HashUtil.hashInput(email)));
        newUser.setValidated(false);

        newUser.updateFts();

        oby.put(newUser);

        return newUser;
    }

    public Key<User> updateUser(User user) {
        user.updateFts();

        return oby.put(user);
    }

    @Override
    public List<User> search(String queryString) {
        Query<User> query = oby.query(User.class);

        Set<String> queryTokens = FullTextSearchUtil
                .getTokensForIndexingOrQuery(queryString,
                        FullTextSearchUtil.MAXIMUM_NUMBER_OF_WORDS_TO_SEARCH);
        List<String> queryTokensList = new ArrayList<String>(queryTokens);

        for (String token : queryTokensList) {
            query.filter("fts", token);
        }

        List<User> result = new ArrayList<User>();
        for (User user : query) {
            result.add(user);
        }

        return result;
    }

}
